package com.hengpeng.common.config;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map.Entry;
import java.util.Observer;
import java.util.Properties;

import org.apache.log4j.Logger;

import com.hengpeng.common.config.expander.PropertiesExpander;
import com.hengpeng.common.config.expander.VariablesExpander;
import com.hengpeng.common.config.monitor.FileMonitorObserver;
import com.hengpeng.common.config.monitor.FileObserver;

/**
 * <pre>
 * Properties工具类
 * 本配置文件支持两种读取方式
 * 1.基于本地文件路径
 * 2.基于源码读取
 * 优先采用文件路径读取
 * </pre>
 * @author chenjian
 * @version 1.0, 2010-12-23
 */
public class PropertiesProvider implements PropertiesExpander
{
	private String filePath;

	private String source;

	private Properties properties = new Properties();

	private FileMonitorObserver<Properties> fileMonitor;

	private VariablesExpander variables;

	private boolean isListenerChange;

	Logger logger = Logger.getLogger(this.getClass());

	protected PropertiesProvider(String filePath, boolean isListenerChange)
	{
		super();
		this.filePath = filePath;
		this.isListenerChange = isListenerChange;
		init();
	}

	protected PropertiesProvider(String source)
	{
		super();
		this.source = source;
		this.isListenerChange = false;
		init();
	}

	private void init()
	{
		variables = new VariablesExpander(this, "${", "}");
		if (isListenerChange)
		{
			fileMonitor = new FileMonitorObserver<Properties>(filePath, this);
		}
		this.reloadConfig();
	}

	@Override
	public Properties getConfig()
	{
		return new Properties(properties);
	}

	@Override
	public String getConfigByKey(String key)
	{
		String value = null;
		value = properties.getProperty(key);
		if (value == null)
		{
			return null;
		}
		return variables.getVariablesExpanderValue(value);
	}

	@Override
	public ConfigProvider<Properties> getConfigProvider()
	{
		return this;
	}

	@Override
	public Observer getObserver()
	{
		return new FileObserver();
	}

	@Override
	public void reloadConfig()
	{
		logger.info("系统正在装载资源文件");
		synchronized (properties)
		{
			this.properties.clear();
			if (variables != null)
			{
				variables.clearCache();
			}
			InputStream inStream = null;
			try
			{
				if (filePath != null)
				{
					inStream = new FileInputStream(this.filePath);
				}
				else if (source != null)
				{
					inStream = new ByteArrayInputStream(source.getBytes("utf-8"));
				}
				this.properties.load(inStream);
				Properties temp_properties = new Properties();
				for (Entry<Object, Object> entry : this.properties.entrySet())
				{
					String key = new String(entry.getKey().toString().getBytes("iso-8859-1"), "utf-8");
					String value = new String(entry.getValue().toString().getBytes("iso-8859-1"), "utf-8");
					temp_properties.put(key, value);
				}
				this.properties = temp_properties;
			}
			catch (IOException e)
			{
				e.printStackTrace();
				logger.error("系统配置文件{" + filePath + "}装载失败");
			}
			finally
			{
				if (inStream != null)
				{
					try
					{
						inStream.close();
					}
					catch (IOException e)
					{
						e.printStackTrace();
					}
				}
			}
			if (isListenerChange)
			{
				Long time = 0l;
				try
				{
					time = Long.valueOf(this.getConfigByKey(ConfigKey.REFRESH_MILLISECOND_TIME));
				}
				catch (Exception ex)
				{
					time = DEFAULT_UPDATE_TIME;
				}
				if (time != null && time > 0)
				{
					fileMonitor.end();
					fileMonitor.start(time * 1000);
				}
				else
				{
					fileMonitor.end();
					fileMonitor.start(DEFAULT_UPDATE_TIME * 1000);
				}
			}
		}
	}

	@Override
	public void putValue(String key, String value)
	{
		this.properties.setProperty(key, value);
	}

	public void setSource(String source)
	{
		this.source = source;
	}
}
